//
//  MtdsManage.swift
//  SwiftZCC
//
//  Created by Mr.Hong on 2019/12/21.
//  Copyright © 2019 Mr.Hong. All rights reserved.
//

import UIKit

// MARK: - 文件路径

/// Library文件夹->Caches文件夹路径;  NSHomeDirectory() + "/Library/Caches"
public let cnm_cacheDirPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
/// Documents文件夹路径;  NSHomeDirectory() + "/Documents"
public let cnm_documentsDirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
/// tmp文件夹路径;  NSHomeDirectory() + "/tmp"
public let cnm_tmpDirPath = NSTemporaryDirectory()

// MARK: - 常规系统函数封装

/// 封装Font;
public func cnmFont(_ ofSize: Double, weight: UIFont.Weight = .regular) -> UIFont {
    return UIFont.systemFont(ofSize: CGFloat(ofSize), weight: weight)
}

/// 封装Font;  粗体
public func cnmBoldFont(_ ofSize: Double) -> UIFont {
    return UIFont.systemFont(ofSize: CGFloat(ofSize), weight: .bold)
}

/// 遍历所有字体
/// - Returns: 所有字体名称
public func cnm_allFontfamilyNames() -> [String] {
    var fonts: Array<String> = []

    for value in UIFont.familyNames {
        fonts.append(value)
    }
    return fonts
}

/// 根据某字体family获取子字体
public func cnm_fontNames(family: String) -> [String] {
    return UIFont.fontNames(forFamilyName: family)
}

/// 封装Image
public func cnmImage(_ named: String? = nil) -> UIImage? {
    guard let named = named else {
        return nil
    }
    return UIImage(named: named)
}

// MARK: - 常量值封装

/// 分割线高度/宽度
public var cnm_cuttingLineHeight: CGFloat {
    return 1 / UIScreen.main.scale
}

/// 获取当前keyWindow
public var cnm_curKeyWindow: UIWindow? {
    if #available(iOS 14.0, *) {
        if let window = UIApplication.shared.connectedScenes.map({ $0 as? UIWindowScene }).compactMap({ $0 }).first?.windows.first {
            return window
        } else if let window = UIApplication.shared.delegate?.window {
            return window
        } else {
            return nil
        }
    } else if #available(iOS 13.0, *) {
        if let window = UIApplication.shared.connectedScenes
            .filter({ $0.activationState == .foregroundActive })
            .map({ $0 as? UIWindowScene })
            .compactMap({ $0 })
            .first?.windows
            .filter({ $0.isKeyWindow }).first {
            return window
        } else if let window = UIApplication.shared.delegate?.window {
            return window
        } else {
            return nil
        }
    } else {
        if let window = UIApplication.shared.delegate?.window {
            return window
        } else {
            return nil
        }
    }
}

/// 是否全面屏(刘海屏) 适配 iOS 13.0+
public var cnm_isFullScreen: Bool {
    if #available(iOS 13, *) { // iOS 13以上系统
        guard let unwrappedWindow = cnm_curKeyWindow else {
            return false
        }

        if unwrappedWindow.safeAreaInsets.left > 0 ||
            unwrappedWindow.safeAreaInsets.bottom > 0 {
            return true
        }
    } else if #available(iOS 11, *) {
        guard let window = cnm_curKeyWindow else {
            return false
        }
        if window.safeAreaInsets.left > 0 || window.safeAreaInsets.bottom > 0 {
            return true
        }
    }
    return false
}

/// 获取导航条高度
public func cnm_getNavBarHeight() -> CGFloat {
    return 44.0 + cnm_statusBarHeight
}

/// 由于iPhone12等机型状态栏高度不是固定的了，所以要动态取状态栏的高度
public var cnm_statusBarHeight: CGFloat {
    var statusBarHeight: CGFloat = 0

    if #available(iOS 13.0, *) {
        if let statusBarManager = UIApplication.shared.windows.first?.windowScene?.statusBarManager {
            statusBarHeight = statusBarManager.statusBarFrame.size.height
        }
        return statusBarHeight
    }

    return UIApplication.shared.statusBarFrame.height
}

/// 获取底部栏高度
public var cnm_getTabBarHeight: CGFloat {
    var tabBarHeight: CGFloat = 49.0

    if cnm_isFullScreen {
        if #available(iOS 11.0, *) {
            tabBarHeight = (cnm_curKeyWindow?.safeAreaInsets.bottom)! + tabBarHeight
        }
    }
    return tabBarHeight
}

/// 随机色
public func cnm_randomColor() -> UIColor {
    let red = CGFloat(arc4random() % 256) / 255.0
    let green = CGFloat(arc4random() % 256) / 255.0
    let blue = CGFloat(arc4random() % 256) / 255.0
    return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}

// MARK: - 特殊函数封装

/// 全局函数 T是泛型 传入不同的参数
public func cnmLog<T>(_ message: T, file: String = #file, funcName: String = #function, lineNum: Int = #line) {
    let file = (file as NSString).lastPathComponent
    // 文件名：行数---要打印的信息
    #if DEBUG

        print("❤️❤️类名：\(file)；🐼🐼行数：\(lineNum)；📚📚内容：\(message)")

    #endif
}

/// 根据字符串获取类;  type: 需要转换成什么类型--> 类名.self
public func cnm_getClass<T>(toType: T.Type, _ clsName: String) -> T.Type? {
    // 获取项目的名称
    let spacename = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String

    guard let className = NSClassFromString(spacename + "." + clsName) else { return nil }

    // 这里的 泛型T 强转必须带上.Type, 否则转换不成功
    guard let classType = className as? T.Type else { return nil }

    return classType
}

/// 是否空字符串
public func cnm_isBlank(_ string: String?) -> Bool {
    guard let str = string else { return true }

    if str.isEmpty { return true }

    if str.replacingOccurrences(of: " ", with: "", options: .literal, range: nil).isEmpty {
        return true
    }
    return false
}

/// 总秒数 转 HH:mm:ss / mm:ss
public func cnm_timeStringWithSecond(_ second: TimeInterval) -> String {
    let time = Int(second)

    if time / 3600 > 0 { // 时分秒
        let hour = time / 3600
        let minute = (time % 3600) / 60
        let second = (time % 3600) % 60

        return String(format: "%02zd:%02zd:%02zd", hour, minute, second)
    } else { // 分秒
        let minute = time / 60
        let second = time % 60

        return String(format: "%02zd:%02zd", minute, second)
    }
}

/**
    比如时间: 13:04
    不足两位补0
    public let time = String(format: "%02d:%02d", arguments: [13, 4])
 */

/// Date转为 DateComponents
public func cnm_dateToComponents(date: Date) -> DateComponents {
    let calendar = Calendar.current
    let rsCmps = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
    return rsCmps
}

/// 比较两个时间差
public func cnm_compareTime(fromDate: Date, toDate: Date) -> DateComponents {
    let zone = TimeZone.current

    let fromInterval = TimeInterval(zone.secondsFromGMT(for: fromDate))
    let toInterval = TimeInterval(zone.secondsFromGMT(for: toDate))

    // 当前date上加一个8小时的时差
    let from_newDate = fromDate.addingTimeInterval(fromInterval)
    let to_newDate = toDate.addingTimeInterval(toInterval)

    let calendar = Calendar.current
    let rsDateCmp = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: from_newDate, to: to_newDate)

    return rsDateCmp
}


/// 是否超过n分钟
/// - Parameters:
///   - minute: 超过的分钟数
///   - time: 时间字符串
/// - Returns: 是否超过
public func cnm_isMoreThanMinute(_ minute: TimeInterval, time: String) -> Bool {
    let dateFmt = DateFormatter()
    dateFmt.dateFormat = "yyyy-MM-dd HH:mm:ss"

    guard let rsDate = dateFmt.date(from: time) else { return false }

    let rsDateCmp = cnm_compareTime(fromDate: Date(), toDate: rsDate)

    if let year = rsDateCmp.year, labs(year) > 0 {
        return true
    }

    if let day = rsDateCmp.day, labs(day) > 0 {
        return true
    }

    if let hour = rsDateCmp.hour, labs(hour) > 0 {
        return true
    }

    if let minute = rsDateCmp.minute, labs(minute) > minute {
        return true
    }

    return false
}


/// 是否为同一天(存储时间与当前时间比较)
/// - Parameters:
///   - lhs: Date 1
///   - rhs: Date 2
/// - Returns: 是否为同一天
public func cnm_isSameDay(lhs: Date, rhs: Date) -> Bool {
    let lhsCmps = cnm_dateToComponents(date: lhs)
    let rhsCmps = cnm_dateToComponents(date: rhs)

    return (lhsCmps.year == rhsCmps.year) && (lhsCmps.month == rhsCmps.month) && (lhsCmps.day == rhsCmps.day)
}


/// 时间戳(以秒为单位)转字符串
/// - Parameters:
///   - timestamp: 时间戳
///   - dateFormat: 时间格式
/// - Returns: 时间格式后（以秒为单位）结果字符串
public func cnm_getTimeSecondString(by timestamp: String, dateFormat: String = "yyyy-MM-dd HH:mm:ss") -> String {
    if timestamp.isEmpty { return "" }

    let date = Date(timeIntervalSince1970: Double(timestamp)!)

    let dateFormatter = DateFormatter()
    dateFormatter.locale = Locale(identifier: "en_US") // 设置你想要的语言环境
    dateFormatter.dateFormat = dateFormat // 设置日期格式

    let dateString = dateFormatter.string(from: date)
    return dateString
}


/// 时间戳(以毫秒为单位)转字符串
/// - Parameters:
///   - timestamp: 时间戳
///   - dateFormat: 时间格式
/// - Returns: 时间格式后（以毫秒为单位）结果字符串
public func cnm_getTimeMillisecondString(by timestamp: String, dateFormat: String = "yyyy-MM-dd HH:mm:ss") -> String {
    if timestamp.isEmpty { return "" }

    guard let timestampInt = Int(timestamp) else { return "" }

    let date = Date(timeIntervalSince1970: TimeInterval(timestampInt / 1000))
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = dateFormat // 设置日期格式

    let dateString = dateFormatter.string(from: date)
    return dateString
}


/// 时间戳转为 08 Mar 2023 | 10:30:41 格式
/// - Parameters:
///   - timestamp: 时间戳
///   - dateFormat: 时间格式
/// - Returns: 对应的格式时间字符串
public func convertTimestampToDateString(timestamp: String, dateFormat: String = "dd MMM yyyy | HH:mm:ss") -> String {
    // 将字符串格式的时间戳转换为 Date 对象
    guard let timestamp = TimeInterval(timestamp) else {
        cnmLog("无效的时间戳")
        return ""
    }
    let date = Date(timeIntervalSince1970: timestamp / 1000) // 获得时间对象

    // 创建一个 DateFormatter 对象并设置日期格式
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = dateFormat

    // 将日期对象转换为指定格式的字符串
    let formattedDate = dateFormatter.string(from: date)
    return formattedDate
}

/// 计算每月天数
/// - Parameters:
///   - year: 年份
///   - month: 月份
/// - Returns: 这个月的总天数
public func cnm_getDaysFromMonth(year: Int, month: Int) -> Int {
    var dayCount = 31
    if (month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12) {
        dayCount = 31
    } else if month == 2 {
        // 判断闰年规则  ①、普通年能被4整除而不能被100整除的为闰年。（如2004年就是闰年,1900年不是闰年）
       //  ②、世纪年能被400整除而不能被3200整除的为闰年。(如2000年是闰年，3200年不是闰年)
        if year % 100 == 0 {
            if (year % 400 == 0 ) && (year % 3200 != 0) {
                dayCount = 29
            } else {
                dayCount = 28
            }
        } else {
            if (year % 4 == 0) && (year % 100 != 0) {
                dayCount = 29
            } else {
                dayCount = 28
            }
        }
    } else {
        dayCount = 30
    }
    return dayCount
}


/// 获取每个中文字的首字母(大写字母);  只取中文第一个字的首字母(大写字母)
/// - Parameters:
///   - chinaText: 中文
///   - allFirst: 是否获取此中文的所有拼音
/// - Returns: 此中文对应的拼音
public func cnm_getPinYin(chinaText: String?, _ allFirst: Bool = true) -> String {
    var py = ""

    if let _chinaText = chinaText, !cnm_isBlank(_chinaText) {
        let valueRef = CFStringCreateMutableCopy(nil, 0, _chinaText as CFString)
        // 转换为带音标的拼音
        CFStringTransform(valueRef, nil, kCFStringTransformToLatin, false)
        // 去掉音标
        CFStringTransform(valueRef, nil, kCFStringTransformStripCombiningMarks, false)
        let pinyinValue = valueRef! as String

        if allFirst {
            // 去掉空格 -> 字符串转换为首字母大写
            let pinyins = pinyinValue.uppercased().components(separatedBy: " ")

            for ch in pinyins {
                // 截取每个拼音的第一个字母
                let firstCha = ch[ch.startIndex].description
                py += firstCha
            }
        } else {
            py = pinyinValue.uppercased()[pinyinValue.startIndex].description
        }
    }
    return py
}


/// 手机号中间6位置* 例子：183******15
/// - Parameter phone: 手机号
/// - Returns: 格式化的手机号
public func cnm_phoneToXing(phone: String) -> String {
    var formatPhone = ""
    
    if !cnm_isBlank(phone) {
        formatPhone = phone
        formatPhone.replaceSubrange(phone.index(phone.startIndex, offsetBy: 3)..<phone.index(phone.endIndex, offsetBy: -2), with: "******")
    }
    return formatPhone
}

/// 小数点后保留 places 位
/// - Parameters:
///   - value: 数值
///   - places: 保留的位数
/// - Returns: 小数点保留后的结果
public func cnm_roundTo(value: CGFloat, places: Int) -> CGFloat {
    let divisor = pow(10.0, CGFloat(places))

    return (value * divisor).rounded() / divisor
}


/// 跳转应用设置
public func cnm_systemSetting() {
    guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
    
    if #available(iOS 10.0, *) {
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    } else {
        UIApplication.shared.openURL(url)
    }
}

/// 打印某个控件的所有属性（包括私有属性）
public func cnm_getPropertys() {
    var i : UInt32 = 0
    var array = class_copyIvarList(UITextField.self, &i)
    var temp = 0
    while temp < i {
        temp += 1
        cnmLog("\(String(cString: ivar_getName((array?.pointee)!)!))")
        array = array?.successor()
    }
}

// MARK: - 跳转App设置界面
public func cnm_openSetting() {
    if let settingURL = URL(string: UIApplication.openSettingsURLString) {
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(settingURL, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(settingURL)
        }
    }
}

// MARK: - 权限授权状态提醒 Alert

/// 提示授权权限并可跳转设置界面，进行授权
/// - Parameters:
///   - option: 某功能名称
///   - content: 描述内容
///   - cancelHandle: 取消事件
public func cnm_authorityAlert(_ option: String, content: String = "相关功能使用", cancelHandle: (() -> Void)? = nil) {
    let contentStr = "您还未授权\(option)权限，是否前往授权用以" + content

    let alertController = UIAlertController(title: "温馨提示", message: contentStr, preferredStyle: .alert)
    let sureAction = UIAlertAction(title: "确定", style: .default) { _ in
        let settingURL = NSURL(string: UIApplication.openSettingsURLString)! as URL
        if UIApplication.shared.canOpenURL(settingURL) {
            if #available(iOS 10.0, *) { // iOS 10以上系统
                UIApplication.shared.open(settingURL, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(settingURL)
            }
        }
    }
    let cancelAction = UIAlertAction(title: "取消", style: .cancel) { _ in
        if let cancelHandle = cancelHandle {
            cancelHandle()
        }
    }
    alertController.addAction(sureAction)
    alertController.addAction(cancelAction)

    cnm_curKeyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
}

/// 拒绝授权功能权限提示框
/// - Parameters:
///   - option: 某功能名称
///   - cancelHandle: 点击确定时间
public func cnm_deniedAlert(_ option: String, cancelHandle: @escaping () -> Void) {
    // 获取项目名称
    let productName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String

    let alertController = UIAlertController(title: "温馨提示", message: "您已拒绝了\(productName)访问你的\(option)权限，如需开启请自行到设置中开启！", preferredStyle: .alert)
    let cancelAction = UIAlertAction(title: "确定", style: .cancel) { _ in
        cancelHandle()
    }
    alertController.addAction(cancelAction)

    cnm_curKeyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
}

// MARK: - 网络请求 响应 code  NSLocalizedFailureReasonErrorKey

public func cnm_getErrorMessage(_ code: Int = -99999) -> String {
    switch code {
    case NSURLErrorTimedOut: // -1001
        return "抱歉，请求超时"
    case NSURLErrorCancelled: // -999
        return "抱歉，请求取消"
    case NSURLErrorCannotConnectToHost: // -1004
        return "抱歉，连接服务器失败"
    case NSURLErrorNotConnectedToInternet: // -1009
        return "抱歉，网络连接失败，请检查网络"
    case NSURLErrorBadServerResponse: // -1011
        return "抱歉，服务器未响应"
    default:
        return "抱歉，请求失败或数据解析失败"
    }
}
